查看原文
其他

Python 从Zero 到 Hero(三)

21CTO 21CTO 2022-05-25


封装:隐藏信息

 

封装是在面向对象编程中一种限制直接访问对象数据以及方法的机制,用来约束对这些数据或方法的操作。

 

也就是说,封装可以用来隐藏数据成员和成员函数。在此定义下,封装意着一个对象的内部表示在对象之外通常是隐藏的。

 

对象的所有内部表现是在外部隐藏的,只有对象可以与其内部数据交互。

 

首先,我们需要了解public与非public实例和方法是如何工作的。

 

公共实例变量

 

对于Python类,我们可以在构造方法中初始化一个public instance variable— 公共实例变量。我们来看以下代码:

 

在构造函数方法中:

 

class Person:

   def __init__(self, first_name):

       self.first_name = first_name

 

在这里,我们把first_name做为一个参数应用于public instance variable。

 

raymond = Person('Raymond');

print(raymond.first_name) # => Raymond

 

在类中:

 

class Person:

  first_name = 'Raymond';

 

在这里,我们无需将first_name做为参数,所有的实例对象都有一个通用的类属性 first_name 值初始化为 Raymond。

 

请看如下代码:

 

ex = Person();

print(ex.first_name) #=>Raymond

 

现在我们已经学习到,可以用公共实例变量和类属性。

有关public另一部分有趣的事情是我们可以管理变量值。这是啥意思? 我们的对象可以管理变量值: get和set变量值。

 

保持 Person 类的思路 ,我们想改变first_name的值。

 

ex = Person('Raymond')

ex.first_name = 'Jason'

print(ex.first_name) # => Jason

 

上面我们就为first_name实例变量设置了一个新值,就是这么简单。

 

非公共实例变量

 

在这儿,我们没有使用术语“Private”,因为在Python中没有任何属性是真正私有的(通常情况下没有必要)。

 

作为通用实例变量,我们可以在构造方法内或类内部定义非全局实例的变量。语法不同之处在于:对于非全局实例变量,请在变量名之前加下划线(_)。

 

其实在Python中不存在除了对象内部不能访问的“私有”实例变量。 但是,大多数的Python代码都有一个约定:前缀加下划线(如_spam)为命名的变量被视为API中非公开的内容(无论是函数,方法还是数据成员)——这是来自Python软件基金会之定义。

 

我们一起来看代码实例:

 

class Person:

  def__init__(self,first_name,email):

self.first_name= first_name

self._email =email

 

您有看到emial变量吗?它被定义成一个非公共变量。

 

ex = Person(‘raymond’,’raymond@21cto.com’)

print(ex._email) # raymond@21cto.com

 

我们可以访问和更新它。非全局实例变量只有一个区别,应该被视为API的非公开部分。

 

因此,我们在类中定义和实现两个方法(email和update_email)来访问更新,如下代码:

 

class Person:

 

  def__init__(self,first_name,email):

     self.first_name = first_name

     self._email = email

 

  defupdate_email(self,new_email):

     self._email = new_email

 

  defemail(self):

     return self._email

 

现在我们可以更新并访问非全局实例变量,使用如下方法。来看下面的代码:

 

ex = Person('raymond','raymond@21cto.com')

print(ex.email()) # => raymond@21cto.com

ex._email = 'raymond1@21cto.com'

print(ex.email()) # => raymond@21cto.com

ex.update_email('raymond1@21cto.com')

print(ex.email()) # =>raymond1@21cto.com

 

 

1 我们初始化了一个新对象first_name 为 raymond 以及 email 为 raymond@21cto.com

2 使用一个方法访问并打印了非全局实例变量 email

3 尝试在我们的类里设置一个新mail

4 我们需要将非全局实例变量视为API的非全局部分

5 用我们的实例方法更新 非全局变量

6 成功!我们可以使用helper方法在我们的类中更新它

 

公共方法

 

在公共方法中,我们可以在类中使用它们:

class Person:

   def __init__(self, first_name, age):

       self.first_name = first_name

       self._age = age

 

   def show_age(self):

       return self._age

 

我们来测试一下:

 

raymond = Person('Rayond', 38)

print(raymond.show_age()) # => 38

 

非常好,我们使用它没有任何问题。

 

非公共方法

 

如果声明为非公共方法,我们就不能随意调用了。我们实现相同的Person类,现在我们把show_age加上下划线(_)。

 

class Person:

   def __init__(self, first_name, age):

       self.first_name = first_name

       self._age = age

 

    def _show_age(self):

       return self._age

 

现在,我们尝试创建新对象来调用这个非公共方法:

 

raymond = Person('Raymond', 38)

print(raymond._show_age()) # => 38

 

我们可以正常访问和更新值。非公共方法只是一个约定惯例,但通常视为API的非公开部分。

 

下面是我们如何使用它的一个示例:

 

class Person:

   def __init__(self, first_name, age):

       self.first_name = first_name

       self._age = age

 

   def show_age(self):

       return self._get_age()

 

   def _get_age(self):

       return self._age

 

raymond = Person('Raymond', 38)

print(raymond.show_age()) # => 38

 

这里有一个_get_age的非公共方法和一个show_age的公共方法。show_age方法可以被我们的对象(不在我们的类中)使用,而_get_age只能用在我们的类定义里面(在show_age方法中)。但是,作为惯例,亦是如此。

 

由此我们总结,通过封装,我们是可以确保对象的内部表示是可以从外部隐藏的。

 

继承:行为和特征

 

某此物体有一些共同之处,比如它们的行为和特征。

 

比如,我继承了父亲的一些特征和行为。比如他的眼睛和头发特征,以及他的不耐烦和内向等行为。

 

在面向对象编程中,类可以继承另一个类的共同特征(数据)和行为(方法)。

 

接下来我们来看一个例子,然后我们用Python来实现它。

 

我们继续来考虑一下汽车。车轮数量,座位容量以及最高时速都是一辆车的属性。比如一个电动汽车 ElectricCar继承了普通 Car类的相同属性。

 

以下是Car汽车类的定义以及属性的定义。

 

class Car:

   def __init__(self, number_of_wheels, seating_capacity,maximum_velocity):

       self.number_of_wheels = number_of_wheels

       self.seating_capacity = seating_capacity

       self.maximum_velocity = maximum_velocity

 

接下来实现Car的类。

 

my_car = Car(4, 5, 250)

print(my_car.number_of_wheels)

print(my_car.seating_capacity)

print(my_car.maximum_velocity)

 

一旦运行,我们可以使用所有创建的实例变量。

 

在Python中,我们可以将父类应用于子类中作为参数。ElectricCar可以继承我们的Car类。

 

class ElectricCar(Car):

   def __init__(self, number_of_wheels, seating_capacity,maximum_velocity):

       Car.__init__(self, number_of_wheels, seating_capacity, maximum_velocity)

 

就是这么方便。我们不需要实现任何其它方法,类已经继承了Car类的所有方法。我们来使用代码证明之:

 

my_electric_car = ElectricCar(4, 5, 250)

print(my_electric_car.number_of_wheels) #=> 4

print(my_electric_car.seating_capacity) #=> 5

print(my_electric_car.maximum_velocity) #=> 250

 

干得漂亮!

 

小结

 

至此,我们已经学到了很多关于Python基础的知识。包括:

  • Python变量的工作方式

  • Python条件语句如何工作

  • Python循环(while和for)是如何工作的

  • 如何使用列表:Collection与排序

  • 字典键值数据结构

  • 如何遍历以上数据结构

  • 对象和类

  • 属性做为对象的数据

  • 方法做为对象的行为

  • 使用Python设置和获取属性

  • 封装:如何隐藏信息

  • 继承:行为和特征

 

祝贺您!我们一起完成为关于Python从入门到应用这一系列密集的内容。

 

有更多关于Python更深入的编程内容,敬请您期待。祝大家生活愉快,不断学习,始终保持最好的编码实践。


作者:21CTO社区

说明:Python基础教程:从Zero到Hero连载已完毕。后续还有继续推出相关文章和课程


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存